#include "StdAfx.h"
#include "Client.h"
using namespace std;
#include <fstream>

Client::Client(char *CN,char *OU,char **DN,int DN_level)
{
	CommonName=new char[strlen(CN)+1];
	OrganizationalUnit=new char[strlen(OU)+1];
	
	DomainName=new char*[DN_level + 1];
	DomainName_level = DN_level;
	
	if(CommonName == 0 || OrganizationalUnit == 0 || DomainName == 0 || DomainName_level == 0)
		throw new exception();

	strcpy(CommonName,CN);
	strcpy(OrganizationalUnit,OU);
	for(int i=0;i<DN_level;i++)
	{
		DomainName[i] = new char[strlen(DN[i]) + 1];
		strcpy(DomainName[i],DN[i]);
	}
	this->Auth_state = false;
	this->isConnected = false;
	
	generateClientDN_DC();
}

Client::Client(char *CN,char **DN,int DN_level)
{
	CommonName=new char[strlen(CN)+1];
	OrganizationalUnit=new char[10];
	
	DomainName=new char*[DN_level + 1];
	DomainName_level = DN_level;
	
	if(CommonName == 0 || OrganizationalUnit == 0 || DomainName == 0 || DomainName_level == 0)
		throw new exception();

	strcpy(CommonName,CN);
	strcpy(OrganizationalUnit,"");
	for(int i=0;i<DN_level;i++)
	{
		DomainName[i] = new char[strlen(DN[i]) + 1];
		strcpy(DomainName[i],DN[i]);
	}
	this->Auth_state = false;
	this->isConnected = false;

	generateClientDN_DC();

}


void Client::generateClientDN_DC()
{
	char dn[100];
	char dc[100];

	strcpy(dn,"");

	strcat(dn,"cn=");
	strcat(dn,CommonName);
	strcat(dn,",");
	

	if(strcmp(OrganizationalUnit,""))
	{
		strcat(dn,"ou=");
		strcat(dn,OrganizationalUnit);
		strcat(dn,",");
	}

	for(int i=0;i<this->DomainName_level;i++)
	{
		strcat(dn,"dc=");
		strcat(dn,DomainName[i]);
		strcat(dn,",");
	}


	dn[strlen(dn)-1]=' ';
	
	strcpy(dc,"cn=admin,");	
	char *p=strstr(dn,"dc=");
	if(p)
	{
		strcat(dc,p);
	}

	printf("%s...%s",dn,dc);

	ClientDC = new char[strlen(dc)+1];
	strcpy(ClientDC,dc);

	ClientDN = new char[strlen(dn)+1];
	strcpy(ClientDN,dn);
}

void Client::connectToServer(char* ServerIpAdd,int PortNumber)
{

	if(isConnected)
	{
		printf("\nYou are already connected to LDAP Server...");
		return;
	}

	network = new ClientNetwork();
	if(!network->MyClientConnection(ServerIpAdd,PortNumber))
		isConnected = true;
	else
	{
		isConnected = false;
		printf("\nConexiunea la server a esuat!...Verificati adresa IP a serverului si portul acestuia...");
	}

	char result[1000];
	strcpy(result,update());

	printf("\n\nMesajul conexiunii:  %s\n\n",result);

}


Client::~Client(void)
{
	if(DomainName != 0)
		delete[] DomainName;


	if(CommonName != 0)
		delete[] CommonName;

	if(OrganizationalUnit != 0)
		delete[] OrganizationalUnit;

}

bool Client::sendActionPackets(LDAP_Operation *ldap_op)
{
	
	if(!network->sendPackets(ldap_op->daResult()))
	{
		printf("\n..Packets send succed...\n");
		return true;
	}
	else
	{
		return false;
	}
	return false;
}

bool Client::sendActionPackets(char *file_name)
{
	if(strstr(file_name,".ldif"))
	{
		FILE *f=fopen(file_name,"r");

		if(!f)
		{
			printf("Eroare!");
			system("pause");
			exit(1);
		}

		char buffer[1024],buff[100];
		strcpy(buffer,"");
		strcat(buffer,"**");
		strcat(buffer,file_name);
		strcat(buffer," ");

		while(fgets(buff,1024,f))
		{
			strcat(buffer,buff);
		}


		if(!network->sendPackets(buffer))
		{
			printf("\n..Packets send succed...\n");
			return true;
		}
		else
		{
			return false;
			//coada de operatii
		}
	}
	else
		if(strstr(file_name,".jpg"))
		{
			char *buffer,*buff;
			int size;

			ifstream file;
			file.open(file_name, ios::in | ios::binary | ios::ate);

			if(file.is_open())
			{
				size = file.tellg();
				buffer = new char[ size ];

				file.seekg(0, ios::beg );
				file.read(buffer , size);
				buffer [size] = 0;
				file.close();
			}
			
			buff = new char[ size + strlen(file_name) + 10];
			strcpy(buff,file_name);
			strcat(buff," ");
			int len = strlen(file_name) + 1;
			for(int i=0;i<size;i++)
				buff[i + len] = buffer[i];
			size = size + len;
			
			if(!network->sendPackets(buff,size))
			{
				printf("\n..Packets send succed...\n");
				return true;
			}
			else
			{
				return false;
				//coada de operatii
			}
		}
	return false;
}





char* Client::update()
{
	strcpy(network_data,"");
    int data_length = network->receivePackets(network_data);


    if (data_length <= 0) 
    {
		strcpy(network_data,"The server send a NULL message!");
    }

	return network_data;
}


void Client::Bind(char *User_name,char *Password)
{

	if(Auth_state)
	{
		printf("\nYou are already logged to LDAP Server...");
		return;
	}

	if(isConnected)
	{
		vector<Atribut<char*>> atribute;

		Atribut<char *> atribut("cn",User_name),atribut2("sn",Password);
		atribute.push_back(atribut);
		atribute.push_back(atribut2);

		char dc[100];
		strcpy(dc,"");

		for(int i=0;i<DomainName_level;i++)
		{
			strcat(dc,"dc");
			strcat(dc,"=");
			strcat(dc,DomainName[i]);
			strcat(dc,",");
		}

		dc[strlen(dc)-1]=' ';
	
		LDAP_Operation *bind_op = new Bind_Operation(dc,atribute);

		bool iResult = this->sendActionPackets(bind_op->operate());

		Bind_Result *bind_res = new Bind_Result(this->update(),iResult,User_name,Password);

		bind_res->afisareResult();

		Auth_state = bind_res->getAuthState();
	}
	else
	{
		printf("\n\n->You must be connected to server first!!...",User_name);
		return;
	}

}


void Client::Search(int auth_type,char **ldapOptions,int nr_opt,char *ldap_URI, bool search_base , vector<Atribut<char*>> filtru)
{
	if(Auth_state)
	{

		LDAP_Operation *search_op = new Search_Operation(ClientDN,auth_type,ldapOptions,nr_opt,ldap_URI,search_base , filtru);

		bool iResult = this->sendActionPackets(search_op->operate());


		Search_Result *search_res = new Search_Result(this->update(),iResult,filtru);
		search_res->afisareResult();

	}
	else
	{
		printf("\n->You must be authenticated to LDAP Server to perform this operation!!");
		return;
	}

}


void Client::Search(int auth_type,char **ldapOptions,int nr_opt,char *ldap_URI, bool search_base)
{

	if(Auth_state)
	{
		LDAP_Operation *search_op = new Search_Operation(ClientDN,auth_type,ldapOptions,nr_opt,ldap_URI,search_base);
	
		bool iResult = this->sendActionPackets(search_op->operate());

		
		Search_Result *search_res = new Search_Result (this->update(),iResult);
		search_res->afisareResult();

	}
	else
	{
		printf("\n->You must be authenticated to LDAP Server to perform this operation!!");
		return;
	}
}



void Client::compareAtribute(char *dn,int auth_type,char **option,int nr_opt,char *ldap_URI,vector<Atribut<char*>> filtru)
{
	if(Auth_state)
	{
		vector<Atribut<char *>> search;
		Atribut<char *> a1("cn",CommonName);
		search.push_back(a1);

		Compare_Operation *compare_op = new Compare_Operation(dn,auth_type,option,nr_opt,ldap_URI,search);

		bool iResult = this->sendActionPackets(compare_op->operate());

		Compare_Result *comp_res = new Compare_Result (this->update(),iResult,filtru);
		comp_res->afisareResult();

	}
	else
	{
		printf("\n->You must be authenticated to LDAP Server to perform this operation!!");
		return;
	}

}



void Client::Unbind_()
{
	int iResult = network->CloseMyConnection();

	if(iResult)
		printf("\n->Clientul %s a fost deconectat cu succes!...",CommonName);
	else
		throw new exception();

	delete network;	
	network=0;
}